/**
 * jgamebox
 *
 * outlook@China software studio
 * Copyright (c) 2008-2011. All Rights Reserved.
 * http://www.outlook.com
 */

package org.outlook.jgamebox.role;

import java.io.Serializable;

import javax.swing.JLabel;

import org.outlook.common.measure.Direction;
import org.outlook.common.measure.Position;
import org.outlook.comon.ai.AIer;
import org.outlook.jgamebox.api.Instance;
import org.outlook.jgamebox.map.Scene;

/**
 * function:
 * @author watson  email: watson.wu@hotmail.com
 * @date 2011-5-29
 */
public class Spriter extends Instance implements Runnable, Cloneable, Serializable {
	
	private static final long serialVersionUID = 1L;

	private int moveProbability = 85;//85%
	private int changeDirectionProbability = 5;//5%

	private JLabel image;
	private Scene scene;

	public Spriter() {
		super();
	}

	public JLabel getImage() {
		return image;
	}

	public void setImage(JLabel image) {
		this.image = image;
	}

	public Scene getScene() {
		return scene;
	}

	public void setScene(Scene scene) {
		this.scene = scene;
	}

	public boolean isBeyondMap() {
		return scene.isBeyondMap(this);
	}
	
	public void move() {
		move(getDirection());
	}

	public void move(final Direction dire) {
		if(!isBeyondMap()) {
			Position position = Direction.move(getPosition(), getSpeed(), dire);
			setPosition(position);
			//just for 2D temporarily
			updateImage2DPosition(getPositionX(), getPositionY());
		} else
			redirect();
	}
	
	private void updateImage2DPosition(int newX, int newY) {
		getImage().setBounds(newX, newY, getWidth(), getHeight());
	}

	public void move(final Direction dire, int step) {
		for(int i=0;i<step;i++)
			move(dire);
	}
	
	public void move(Direction[] dires) {
		if(!isBeyondMap()) {
			Position position = Direction.move3D(getPosition(), getSpeed(), dires, 1);
			setPosition(position);
			//just for 2D temporarily
			updateImage2DPosition(getPositionX(), getPositionY());
		} else
			redirect();
	}
	
	public void move(Direction[] dires, int step) {
		if(dires.length > 3)
			//report error
			;
		for(int i=0;i<step;i++)
			move(dires);
	}
	
	public void moveXY(Direction[] dires) {
		if(dires.length > 2)
			//report error
			;
		
		int newX = getPositionX();
		int newY = getPositionY();
		if(dires[0] == Direction.LEFT)
			newX -= getSpeedX();
		else
			newX += getSpeedX();
		if(dires[1] == Direction.UP)
			newY -= getSpeedY();
		else
			newY += getSpeedY();
		
		getImage().setBounds(newX, newY, getWidth(), getHeight());
		getPosition().setX(newX);
		getPosition().setY(newY);
	}
	
	public void moveXY(Direction[] dires, final int step) {
		if(dires.length > 2)
			//report error
			;

//		Timer timer = new Timer();
//		timer.schedule(new TimerTask() {
//
//			@Override
//			public void run() {
//			}
//			
//		}, 0, 50);
		for(int i=0;i<step;i++)
			moveXY(dires);
	}
	
	public Direction redirect() {
		//just 2D temporarily
		//getAvailableDirection()
		return redirect(Direction.valueOf(AIer.random(Direction.values().length)));
	}
	
	public Direction redirect(Direction direction) {
		setDirection(direction);
		return getDirection();
	}

	@Override
	public void run() {
		while(isAlive()) {
			if(shouldMove())
				move();
			if(shouldChangeDirection())
				redirect();
		}
		destory();
	}

	public boolean shouldChangeDirection() {
		return AIer.isHit(getChangeDirectionProbability());
	}

	public boolean shouldMove() {
		return AIer.isHit(getMoveProbability());
	}
	
	public void destory() {
		//TODO
		getImage().setVisible(false);
	}

	public int getMoveProbability() {
		return moveProbability;
	}

	public void setMoveProbability(int moveProbability) {
		if(moveProbability>0 && moveProbability<100)
			this.moveProbability = moveProbability;
		else
			//report error;
			;
	}

	public int getChangeDirectionProbability() {
		return changeDirectionProbability;
	}

	public void setChangeDirectionProbability(int changeDirectionProbability) {
		if(changeDirectionProbability>0 && changeDirectionProbability<100)
			this.changeDirectionProbability = changeDirectionProbability;
		else
			//report error;
			;
	}

}